#include <stdio.h>
#include <stdlib.h>

#include "../tdp2/tdp2_threading.hpp"
#include "../../rdx/src/lua/src/lauxlib.h"
#include "toolbox.hpp"

struct MultiExecuteInstance
{
	const char **lines;
	unsigned int numExecutes;
	volatile unsigned int currentExecute;
	volatile int errorCode;
	TDP::Threading::LightMutex mutex;
};

#define MAX_THREADS	16

struct MEIExecuteProc : public TDP::Threading:: ISystemThreadProc
{
	MultiExecuteInstance *mei;

	void Start() const
	{
		while(true)
		{
			mei->mutex.Acquire();

			if(mei->errorCode != 0 || mei->currentExecute == mei->numExecutes)
			{
				mei->mutex.Release();
				return;
			}

			const char *exec = mei->lines[mei->currentExecute++];
			mei->mutex.Release();

			int returnCode = system(exec);

			if(returnCode)
			{
				mei->mutex.Acquire();
				mei->errorCode = returnCode;
				mei->mutex.Release();
				return;
			}
		}
	}
};

int MultiExecute(const char **lines, unsigned int numExecutes)
{
	MultiExecuteInstance mei;
	TDP::Threading::ISystemThread *threads[MAX_THREADS];
	mei.lines = lines;
	mei.numExecutes = numExecutes;
	mei.currentExecute = 0;
	mei.errorCode = 0;

	MEIExecuteProc proc;
	proc.mei = &mei;

	int numThreads = TDP::Threading::CountProcessors();
	if(numThreads > MAX_THREADS)
		numThreads = MAX_THREADS;

	for(unsigned int i=0;i<numThreads;i++)
		threads[i] = TDP::Threading::CreateSystemThread(&proc);
	for(unsigned int i=0;i<numThreads;i++)
	{
		while(threads[i]->IsActive())
		{
			threads[i]->WaitFor(1000);
			printf("Scattershot job: %i / %i\r", mei.currentExecute+1, mei.numExecutes);
		}
	}

	for(unsigned int i=0;i<numThreads;i++)
		TDP::Threading::DestroySystemThread(threads[i]);

	printf("Scattershot job completed!                               \n");
	return mei.errorCode;
}
